'use strict'
const path = require('path')
const webpack = require('webpack')
const autoprefixer = require('autoprefixer')
const htmlWebpackPlugin = require('html-webpack-plugin')
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
const CompressionPlugin = require('compression-webpack-plugin')
const CleanWebpackPlugin = require('clean-webpack-plugin')
const WorkboxPlugin = require('workbox-webpack-plugin')
const CopyWebpackPlugin = require('copy-webpack-plugin')

module.exports = {
    entry: {
        app: path.resolve(__dirname, 'src/index.jsx'),
    },
    output: {
        path: path.resolve(__dirname, 'build'),
        filename: 'js/[name].[chunkhash:5].js',
    },

    resolve: {
        extensions: ['.js', '.jsx', '.css','.less'],
        alias: {
            '@': path.resolve(__dirname, './src'),
            'components': path.resolve(__dirname, './src/components'),
            'pages': path.resolve(__dirname, './src/pages'),
            'fetch': path.resolve(__dirname, './src/fetch'),
            'mock': path.resolve(__dirname, './mock'),
            'iconfont': path.resolve(__dirname, './src/static/iconfont'),
            'static': path.resolve(__dirname, './src/static'),
            'reducers': path.resolve(__dirname, './src/redux/reducers'),
            'utils': path.resolve(__dirname, './src/utils'),
            'public': path.resolve(__dirname, './public'),
        },
    },

    module: {
        rules: [
            {
                test: /\.(js|jsx)$/,
                exclude: /node_modules/,
                loader: 'babel-loader',
                options: {
                    presets: ['@babel/preset-react', ["@babel/preset-env",{"useBuiltIns": "entry"}]],
                    plugins: [
                        'react-html-attrs',
                        ["@babel/plugin-proposal-decorators", { "legacy": true }]
                    ],
                },
            },
            {
                test: /\.(css|less)$/,
                exclude: [
                    path.resolve(__dirname, 'node_modules'),
                    path.resolve(__dirname, 'src/static'),
                    path.resolve(__dirname, 'src/utils'),
                ],
                include: path.resolve(__dirname, 'src'),
                use: [{
                    loader: MiniCssExtractPlugin.loader,
                    options: {
                        publicPath: "./"
                    }},
                    {
                        loader: 'css-loader',
                        options: {
                            minimize: true,
                            modules: true,
                            localIdentName: '[name]_[local]_[hash:base64:5]',
                        },
                    },
                    {
                        loader: 'postcss-loader',
                        options: {
                            ident: 'postcss',
                            plugins:[
                                // 雪碧图
                                /*require('postcss-sprites')({
                                    spritePath: 'build/images/'
                                }),*/
                                // 修复flexbug
                                require('postcss-flexbugs-fixes'),
                                // css浏览器前缀
                                require('autoprefixer')({
                                    browsers: ['ios>=8'],
                                    flexbox: 'no-2009',
                                }),
                            ],
                        },
                    },
                    {
                        loader: 'less-loader',
                    },
                ],
            },
            {
                test: /\.css$/,
                loader: 'style-loader!css-loader'
            },
            {
                test: /\.(png|gif|jpg|jpeg|bmp)$/i,
                exclude: /node_modules/,
                use: [
                    {
                        loader: 'url-loader',
                        options: {
                            name: '[name]-[hash:5].[ext]',
                            limit: 2048,
                            publicPath: '../images',
                            outputPath: 'images/',
                            //useRelativePath: true
                        },
                    },
                    {
                        loader: 'img-loader',
                        options: {
                            plugins: [
                                require('imagemin-gifsicle')({
                                    interlaced: false
                                }),
                                require('imagemin-mozjpeg')({
                                    progressive: true,
                                    arithmetic: false
                                }),
                                require('imagemin-pngquant')({
                                    floyd: 0.5,
                                    speed: 2
                                }),
                                require('imagemin-svgo')({
                                    plugins: [
                                        { removeTitle: true },
                                        { convertPathData: false }
                                    ]
                                })
                            ]
                        }
                    },
                ],
            },
            {
                test: /\.svg$/,
                exclude: /node_modules/,
                exclude: path.resolve(__dirname, 'src/static/iconfont'),
                use: [
                    {
                        loader: 'url-loader',
                        options: {
                            name: '[name]-[hash:5].[ext]',
                            limit: 5000,
                            outputPath: 'images/',
                        },
                    },
                ],
            },
            {
                test: /\.(eot|svg|ttf|otf|woff?|woff2?)$/,
                include: path.resolve(__dirname, 'src/static/iconfont'),
                use: [
                    {
                        loader: 'url-loader',
                        options: {
                            name: '[name]-[hash:5].[ext]',
                            limit: 5000,
                            //publicPath: './',
                            outputPath: 'fonts/',
                            //useRelativePath: true
                        },
                    },
                ],
            },
        ],
    },

    // 提供公共代码
    optimization: {
        splitChunks: {
            chunks: 'all',
            minSize: 30000,
            minChunks: 1,
            maxAsyncRequests: 5,
            maxInitialRequests: 3,
            automaticNameDelimiter: '~',
            name: true,
            cacheGroups: {
                vendors: {
                    test: /[\\/]node_modules[\\/]/,
                    priority: -10,
                    enforce: true
                },
                default: {
                    minChunks: 2,
                    priority: -20,
                    reuseExistingChunk: true
                }
            }
        }
    },

    plugins: [
        // webpack 内置的 banner-plugin
        new webpack.BannerPlugin('Copyright by xuhongling'),

        // html 模板插件
        new htmlWebpackPlugin({
            title: 'React App',
            favicon: __dirname + '/public/favicon.ico',
            template: __dirname + '/public/index.html',
            minify: {
                removeComments: true,
                collapseWhitespace: true,
                removeRedundantAttributes: true,
                useShortDoctype: true,
                removeEmptyAttributes: true,
                removeStyleLinkTypeAttributes: true,
                keepClosingSlash: true,
                minifyJS: true,
                minifyCSS: true,
                minifyURLs: true,
            },
            chunksSortMode:'dependency'
        }),

        // 定义为生产环境，编译 React 时压缩到最小
        new webpack.DefinePlugin({
            'process.env': {
                NODE_ENV: JSON.stringify('production'),
            },
        }),

        //删除之前的打包目录
        new CleanWebpackPlugin(['build']),

        // 在打包时忽略本地化内容
        new webpack.IgnorePlugin(/\/public$/),

        // 在「生产/开发」构建中使用不同的服务URL(Service URLs)
        new webpack.DefinePlugin({
            'APP_URL': JSON.stringify('http://aaa.example.com')
        }),

        // 代码打包的体积变得更小，加快运行的速度
        new webpack.optimize.ModuleConcatenationPlugin(),

        // 为组件分配ID，通过这个插件webpack可以分析和优先考虑使用最多的模块，并为它们分配最小的ID
        new webpack.optimize.OccurrenceOrderPlugin(),

        // 分离CSS文件
        new MiniCssExtractPlugin({
            filename: "css/[name].[chunkhash:5].css"
        }),

        // 将资源文件压缩为.gz文件
        new CompressionPlugin({
            test: /\.js$|\.css$|\.html$|\.eot?.+$|\.ttf?.+$|\.woff?.+$|\.svg?.+$/,
            filename: '[path].gz[query]',
            algorithm: 'gzip',
            threshold: 10240,
            minRatio: 0.8,
            deleteOriginalAssets: false
        }),

        new webpack.LoaderOptionsPlugin({
            minimize: true,
            debug: false,
        }),

        new WorkboxPlugin.GenerateSW({
            skipWaiting: true, // 强制等待中的 Service Worker 被激活
            clientsClaim: true, // Service Worker 被激活后使其立即获得页面控制权
        }),

        new CopyWebpackPlugin([
            {
                from: './public/manifest.json',
                to: 'manifest.json'
            },
            {
                from: './public/images/logo_144.png',
                to: 'images/logo_144.png'
            },
            {
                from: path.resolve(__dirname, './public'),
                to: path.resolve(__dirname, './build'),
                ignore: ['.*']
            }
        ]),
    ],
}